package xyz.zyt123.hikvideo.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttribute;
import xyz.zyt123.hikvideo.bean.Camera;
import xyz.zyt123.hikvideo.bean.Capture;
import xyz.zyt123.hikvideo.bean.Device;
import xyz.zyt123.hikvideo.bean.User;
import xyz.zyt123.hikvideo.common.AjaxResult;
import xyz.zyt123.hikvideo.common.PageQuery;
import xyz.zyt123.hikvideo.config.VideoConfig;
import xyz.zyt123.hikvideo.service.CaptureService;
import xyz.zyt123.hikvideo.service.DeviceService;
import xyz.zyt123.hikvideo.service.SysLogService;
import xyz.zyt123.hikvideo.service.VideoService;
import xyz.zyt123.hikvideo.util.CacheUtil;
import xyz.zyt123.hikvideo.util.CameraThread;
import xyz.zyt123.hikvideo.util.CaptureMgr;
import xyz.zyt123.hikvideo.util.VideoMgr;
import xyz.zyt123.hikvideo.util.VideoThread;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author zhuyuntao
 */
@RestController
@RequestMapping("/api/v1/device")
public class DeviceController {

  @Autowired
  private DeviceService deviceService;
  @Autowired
  private VideoConfig videoConfig;
  @Autowired
  private CaptureService captureService;
  @Autowired
  private VideoService videoService;
  @Autowired
  private SysLogService sysLogService;

  public static final Map<Integer, CameraThread.MyRunnable> jobMap = new HashMap<>();

  /**
   * capture id 设备ID
   **/
  @GetMapping(value = "/capture")
  public AjaxResult<Void> capture(@RequestParam("id") Integer id, @SessionAttribute("user") User user) {
    sysLogService.saveSysLog(user, "执行抓拍");
    Device device = deviceService.getById(id);
    if (device == null) {
      return AjaxResult.fail("设备不存在");
    }
    CaptureMgr capture = new CaptureMgr(device.getIp(), "8000", device.getUsername(), device.getPassword(), videoConfig.getPicture(), device);
    File img = capture.capture();
    if (img == null) {
      return AjaxResult.fail("抓拍失败");
    }
    Capture entity = new Capture();
    entity.setTime(new Date());
    entity.setUserId(user.getId());
    entity.setUserName(user.getNickname());
    entity.setPath(img.getName());
    entity.setDeviceId(device.getId());
    captureService.save(entity);
    return AjaxResult.success();
  }


  /**
   * capture id 设备ID
   **/
  @GetMapping(value = "/video")
  public AjaxResult<Void> video(@RequestParam("id") Integer id, @RequestParam("time") Integer time, @SessionAttribute("user") User user) {
    sysLogService.saveSysLog(user, "录制回放");
    if (CacheUtil.VIDEO_CACHE.get(id) != null) {
      return AjaxResult.fail("正在录制，请不要重复录制。");
    }
    Device device = deviceService.getById(id);
    if (device == null) {
      return AjaxResult.fail("设备不存在");
    }
    startVideo(time, user, device);
    return AjaxResult.success();
  }

  private void startVideo(Integer time, User user, Device device) {
    VideoMgr video = new VideoMgr(device.getIp(), "8000", device.getUsername(), device.getPassword(), videoConfig.getVideo(), time, device);
    VideoThread thread = new VideoThread(video, videoService, user, "手动抓拍");
    thread.start();
    CacheUtil.VIDEO_CACHE.put(device.getId(), thread);
  }


  /**
   * 开始录制
   *
   * @param deviceId
   *     设备ID
   * @param user
   *     用户
   * @param reason
   *     原因
   * @param time
   *     录制时长（分钟）
   */
  @PostMapping("/warning")
  public void startVideo(String deviceId, @SessionAttribute("user") User user, String reason, Integer time) {
    warning(deviceId, user, reason, time);
  }

  public void warning(String deviceId, User user, String reason, Integer time) {
    sysLogService.saveSysLog(user, "告警录制：" + reason);
    Device device = deviceService.getById(deviceId);
    if (device == null) {
      return;
    }
    VideoMgr video = new VideoMgr(device.getIp(), "8000", device.getUsername(), device.getPassword(), videoConfig.getVideo(), time, device);
    VideoThread thread = new VideoThread(video, videoService, user, "手动抓拍");
    thread.start();
  }


  /**
   * openCamera id 设备ID
   *
   * @return Map<String, String>
   **/
  @GetMapping(value = "/cameras")
  public AjaxResult<String> openCamera(@RequestParam("id") Integer id) {
    Device device = deviceService.getById(id);
    if (device == null) {
      return AjaxResult.fail("设备不存在");
    }

    // 获取当前时间
    String openTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date().getTime());
    Set<Integer> keys = CacheUtil.STREAMMAP.keySet();
    if (keys.contains(device.getId())) {
      Camera cameraPojo = CacheUtil.STREAMMAP.get(device.getId());
      cameraPojo.setOpenTime(openTime);
    } else {
      openStream(device, openTime);
    }
    return AjaxResult.success(device.getId() + "/" + device.getId() + ".m3u8");
  }

  /**
   *
   **/
  private void openStream(Device device, String openTime) {
    Camera cameraPojo = new Camera();
    String rtsp = "rtsp://" + device.getUsername() + ":" + device.getPassword() + "@" + device.getIp() + ":" + device.getPort() + "//Streaming/Channels/" + device.getChannel();
    cameraPojo.setUsername(device.getUsername());
    cameraPojo.setPassword(device.getPassword());
    cameraPojo.setIp(device.getIp());
    cameraPojo.setRtsp(rtsp);
    cameraPojo.setOutput(videoConfig.getPath() + device.getId() + "/" + device.getId() + ".m3u8");
    cameraPojo.setOpenTime(openTime);
    cameraPojo.setToken(device.getId());
    // 执行任务
    CameraThread.MyRunnable job = new CameraThread.MyRunnable(cameraPojo);
    CameraThread.MyRunnable.es.execute(job);
    jobMap.put(device.getId(), job);
  }


  @PostMapping("/page")
  public AjaxResult<Page<Device>> page(@RequestBody PageQuery pageQuery) {
    return AjaxResult.success(deviceService.page(new Page<>(pageQuery.getCurrent(), pageQuery.getSize())));
  }

  @GetMapping("/{id}")
  public AjaxResult<Device> get(@PathVariable("id") Integer id) {
    return AjaxResult.success(deviceService.getById(id));
  }

  @PutMapping("/{id}")
  public AjaxResult<Void> update(@PathVariable("id") Integer id, @RequestBody Device device) {
    device.setId(id);
    deviceService.updateById(device);
    if (device.getVideo() == 1) {
      User user = new User();
      user.setId(-1);
      user.setNickname("system");
      startVideo(-1, user, device);
    }
    return AjaxResult.success();
  }

  @PostMapping
  public AjaxResult<Void> add(@RequestBody Device device, @SessionAttribute("user") User loginUser) {
    sysLogService.saveSysLog(loginUser, "添加设备");
    deviceService.save(device);
    if (device.getVideo() == 1) {
      User user = new User();
      user.setId(-1);
      user.setNickname("system");
      startVideo(-1, user, device);
    }
    return AjaxResult.success();
  }

  @DeleteMapping("/{id}")
  public AjaxResult<Void> delete(@PathVariable("id") Integer id, @SessionAttribute("user") User loginUser) {
    sysLogService.saveSysLog(loginUser, "删除设备");
    deviceService.removeById(id);
    if (CacheUtil.VIDEO_CACHE.get(id) != null) {
      CacheUtil.PLAY_BACK.get(id).interrupt();
      CacheUtil.PLAY_BACK.remove(id);
    }
    return AjaxResult.success();
  }


}
